package org.cybzacg.encryption.monitoring.metrics;

import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.OperatingSystemMXBean;
import java.lang.management.ThreadMXBean;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;

/**
 * 性能指标类
 * 收集和统计系统性能相关的指标数据
 * 
 * @author encryption team
 * @version 1.0
 */
public class PerformanceMetrics {
    
    // 时间统计
    private final AtomicLong startTime = new AtomicLong(System.currentTimeMillis());
    private final AtomicLong totalUptime = new AtomicLong(0);
    
    // 内存统计
    private volatile long maxMemory = 0;
    private volatile long usedMemory = 0;
    private volatile long freeMemory = 0;
    
    // CPU统计
    private volatile double cpuUsage = 0.0;
    private volatile int availableProcessors = 0;
    
    // 线程统计
    private volatile int threadCount = 0;
    private volatile long peakThreadCount = 0;
    private volatile long totalStartedThreadCount = 0;
    
    // 吞吐量统计
    private final AtomicLong totalOperations = new AtomicLong(0);
    private final AtomicReference<Long> lastOperationTime = new AtomicReference<>(System.currentTimeMillis());
    private volatile double operationsPerSecond = 0.0;
    
    // 响应时间统计
    private final AtomicLong totalResponseTime = new AtomicLong(0);
    private final AtomicLong responseCount = new AtomicLong(0);
    private volatile double averageResponseTime = 0.0;
    private volatile long maxResponseTime = 0;
    private volatile long minResponseTime = Long.MAX_VALUE;
    
    // 错误统计
    private final AtomicLong errorCount = new AtomicLong(0);
    private final AtomicLong timeoutCount = new AtomicLong(0);
    
    // 系统负载
    private volatile double systemLoadAverage = 0.0;
    
    /**
     * 更新性能指标
     */
    public void update() {
        updateMemoryMetrics();
        updateCPUMetrics();
        updateThreadMetrics();
        updateSystemLoad();
        updateThroughputMetrics();
    }
    
    /**
     * 记录操作
     */
    public void recordOperation() {
        totalOperations.incrementAndGet();
        lastOperationTime.set(System.currentTimeMillis());
        updateThroughputMetrics();
    }
    
    /**
     * 记录响应时间
     * 
     * @param responseTime 响应时间（毫秒）
     */
    public void recordResponseTime(long responseTime) {
        totalResponseTime.addAndGet(responseTime);
        responseCount.incrementAndGet();
        
        // 更新平均响应时间
        averageResponseTime = (double) totalResponseTime.get() / responseCount.get();
        
        // 更新最大响应时间
        if (responseTime > maxResponseTime) {
            maxResponseTime = responseTime;
        }
        
        // 更新最小响应时间
        if (responseTime < minResponseTime) {
            minResponseTime = responseTime;
        }
    }
    
    /**
     * 记录错误
     */
    public void recordError() {
        errorCount.incrementAndGet();
    }
    
    /**
     * 记录超时
     */
    public void recordTimeout() {
        timeoutCount.incrementAndGet();
    }
    
    /**
     * 获取启动时间
     * 
     * @return 启动时间戳
     */
    public long getStartTime() {
        return startTime.get();
    }
    
    /**
     * 获取运行时间
     * 
     * @return 运行时间（毫秒）
     */
    public long getUptime() {
        return System.currentTimeMillis() - startTime.get();
    }
    
    /**
     * 获取最大内存
     * 
     * @return 最大内存（字节）
     */
    public long getMaxMemory() {
        return maxMemory;
    }
    
    /**
     * 获取已使用内存
     * 
     * @return 已使用内存（字节）
     */
    public long getUsedMemory() {
        return usedMemory;
    }
    
    /**
     * 获取可用内存
     * 
     * @return 可用内存（字节）
     */
    public long getFreeMemory() {
        return freeMemory;
    }
    
    /**
     * 获取内存使用率
     * 
     * @return 内存使用率（0.0-1.0）
     */
    public double getMemoryUsageRate() {
        return maxMemory > 0 ? (double) usedMemory / maxMemory : 0.0;
    }
    
    /**
     * 获取CPU使用率
     * 
     * @return CPU使用率（0.0-1.0）
     */
    public double getCpuUsage() {
        return cpuUsage;
    }
    
    /**
     * 获取可用处理器数
     * 
     * @return 可用处理器数
     */
    public int getAvailableProcessors() {
        return availableProcessors;
    }
    
    /**
     * 获取线程数
     * 
     * @return 当前线程数
     */
    public int getThreadCount() {
        return threadCount;
    }
    
    /**
     * 获取峰值线程数
     * 
     * @return 峰值线程数
     */
    public long getPeakThreadCount() {
        return peakThreadCount;
    }
    
    /**
     * 获取总启动线程数
     * 
     * @return 总启动线程数
     */
    public long getTotalStartedThreadCount() {
        return totalStartedThreadCount;
    }
    
    /**
     * 获取总操作数
     * 
     * @return 总操作数
     */
    public long getTotalOperations() {
        return totalOperations.get();
    }
    
    /**
     * 获取每秒操作数
     * 
     * @return 每秒操作数
     */
    public double getOperationsPerSecond() {
        return operationsPerSecond;
    }
    
    /**
     * 获取平均响应时间
     * 
     * @return 平均响应时间（毫秒）
     */
    public double getAverageResponseTime() {
        return averageResponseTime;
    }
    
    /**
     * 获取最大响应时间
     * 
     * @return 最大响应时间（毫秒）
     */
    public long getMaxResponseTime() {
        return maxResponseTime;
    }
    
    /**
     * 获取最小响应时间
     * 
     * @return 最小响应时间（毫秒）
     */
    public long getMinResponseTime() {
        return minResponseTime == Long.MAX_VALUE ? 0 : minResponseTime;
    }
    
    /**
     * 获取错误数
     * 
     * @return 错误数
     */
    public long getErrorCount() {
        return errorCount.get();
    }
    
    /**
     * 获取超时数
     * 
     * @return 超时数
     */
    public long getTimeoutCount() {
        return timeoutCount.get();
    }
    
    /**
     * 获取错误率
     * 
     * @return 错误率（0.0-1.0）
     */
    public double getErrorRate() {
        long total = totalOperations.get();
        return total > 0 ? (double) errorCount.get() / total : 0.0;
    }
    
    /**
     * 获取超时率
     * 
     * @return 超时率（0.0-1.0）
     */
    public double getTimeoutRate() {
        long total = totalOperations.get();
        return total > 0 ? (double) timeoutCount.get() / total : 0.0;
    }
    
    /**
     * 获取系统负载平均值
     * 
     * @return 系统负载平均值
     */
    public double getSystemLoadAverage() {
        return systemLoadAverage;
    }
    
    /**
     * 更新内存指标
     */
    private void updateMemoryMetrics() {
        try {
            MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();
            maxMemory = memoryBean.getHeapMemoryUsage().getMax();
            usedMemory = memoryBean.getHeapMemoryUsage().getUsed();
            freeMemory = maxMemory - usedMemory;
        } catch (Exception e) {
            // 忽略异常，使用默认值
        }
    }
    
    /**
     * 更新CPU指标
     */
    private void updateCPUMetrics() {
        try {
            OperatingSystemMXBean osBean = ManagementFactory.getOperatingSystemMXBean();
            availableProcessors = osBean.getAvailableProcessors();
            
            // 使用反射安全地获取CPU使用率
            try {
                java.lang.reflect.Method method = osBean.getClass().getMethod("getProcessCpuLoad");
                Object result = method.invoke(osBean);
                if (result instanceof Double) {
                    cpuUsage = (Double) result;
                }
            } catch (Exception e) {
                // 如果反射失败，使用系统负载平均值作为替代
                double systemLoad = osBean.getSystemLoadAverage();
                if (systemLoad >= 0 && availableProcessors > 0) {
                    cpuUsage = Math.min(systemLoad / availableProcessors, 1.0);
                }
            }
        } catch (Exception e) {
            // 忽略异常，使用默认值
        }
    }
    
    /**
     * 更新线程指标
     */
    private void updateThreadMetrics() {
        try {
            ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
            threadCount = threadBean.getThreadCount();
            peakThreadCount = threadBean.getPeakThreadCount();
            totalStartedThreadCount = threadBean.getTotalStartedThreadCount();
        } catch (Exception e) {
            // 忽略异常，使用默认值
        }
    }
    
    /**
     * 更新系统负载
     */
    private void updateSystemLoad() {
        try {
            OperatingSystemMXBean osBean = ManagementFactory.getOperatingSystemMXBean();
            systemLoadAverage = osBean.getSystemLoadAverage();
        } catch (Exception e) {
            // 忽略异常，使用默认值
        }
    }
    
    /**
     * 更新吞吐量指标
     */
    private void updateThroughputMetrics() {
        long currentTime = System.currentTimeMillis();
        Long lastTime = lastOperationTime.get();
        
        if (lastTime != null && currentTime > lastTime) {
            long timeDiff = currentTime - lastTime;
            if (timeDiff > 0) {
                operationsPerSecond = 1000.0 / timeDiff;
            }
        }
    }
    
    /**
     * 重置所有指标
     */
    public void reset() {
        startTime.set(System.currentTimeMillis());
        totalUptime.set(0);
        
        maxMemory = 0;
        usedMemory = 0;
        freeMemory = 0;
        
        cpuUsage = 0.0;
        availableProcessors = 0;
        
        threadCount = 0;
        peakThreadCount = 0;
        totalStartedThreadCount = 0;
        
        totalOperations.set(0);
        lastOperationTime.set(System.currentTimeMillis());
        operationsPerSecond = 0.0;
        
        totalResponseTime.set(0);
        responseCount.set(0);
        averageResponseTime = 0.0;
        maxResponseTime = 0;
        minResponseTime = Long.MAX_VALUE;
        
        errorCount.set(0);
        timeoutCount.set(0);
        
        systemLoadAverage = 0.0;
    }
    
    @Override
    public String toString() {
        return String.format(
            "PerformanceMetrics:\n" +
            "  Uptime: %dms\n" +
            "  Memory: %d/%d MB (%.1f%% used)\n" +
            "  CPU: %.1f%% (%d processors)\n" +
            "  Threads: %d (Peak: %d, Total Started: %d)\n" +
            "  Operations: %d (%.2f ops/sec)\n" +
            "  Response Time: Avg=%.2fms, Max=%dms, Min=%dms\n" +
            "  Errors: %d (Rate: %.2f%%), Timeouts: %d (Rate: %.2f%%)\n" +
            "  System Load: %.2f",
            getUptime(),
            usedMemory / 1024 / 1024, maxMemory / 1024 / 1024, getMemoryUsageRate() * 100,
            cpuUsage * 100, availableProcessors,
            threadCount, peakThreadCount, totalStartedThreadCount,
            getTotalOperations(), getOperationsPerSecond(),
            getAverageResponseTime(), getMaxResponseTime(), getMinResponseTime(),
            getErrorCount(), getErrorRate() * 100, getTimeoutCount(), getTimeoutRate() * 100,
            getSystemLoadAverage()
        );
    }
}
